package com.startx.core.system;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.util.StringUtils;

import com.startx.core.config.ConfigHolder;
import com.startx.core.mvc.define.BodyType;
import com.startx.core.system.config.StartxConfig;
import com.startx.core.system.constants.Constants;
import com.startx.core.system.param.HttpBody;
import com.startx.core.system.param.HttpContext;
import com.startx.core.system.param.HttpForm;
import com.startx.core.system.param.HttpHeader;
import com.startx.core.system.param.HttpParam;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.MixedFileUpload;

/**
 * 获取Http数据
 * @author minghu.zhang
 */
public class HttpParser {
	
	/**
	 * 项目配置
	 */
	private static StartxConfig config = ConfigHolder.getConfig();

	/**
	 * 获取header参数
	 */
	public static HttpHeader getHttpHeader(FullHttpRequest request) {
		Map<String, String> headers = new HashMap<String, String>();

		List<Map.Entry<String, String>> entryList = request.headers().entries();
		for (Map.Entry<String, String> entry : entryList) {
			String key = entry.getKey();
			headers.put(key, entry.getValue());
		}

		return new HttpHeader(headers);
	}

	/**
	 * 获取表单数据
	 * 
	 * @param request
	 * @return
	 * @throws IOException
	 */
	public static HttpForm getHttpForm(FullHttpRequest request) throws IOException {

		HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(request);
		List<InterfaceHttpData> inputs = decoder.getBodyHttpDatas();
		
		HttpForm form = new HttpForm();
		for (InterfaceHttpData input : inputs) {

			if (input instanceof MixedFileUpload) {
				MixedFileUpload data = (MixedFileUpload) input;
				form.upload(input.getName(), data);
			}

			if (input instanceof Attribute) {
				Attribute data = (Attribute) input;
				form.param(data.getName(), data.getValue());
			}
		}

		return form;
	}

	/**
	 * 获取Http上下文环境
	 * 
	 * @param ctx
	 * @param request
	 * @return
	 */
	public static HttpContext getHttpContext(ChannelHandlerContext ctx, FullHttpRequest request) {
		return new HttpContext(getIp(ctx), ctx);
	}

	/**
	 * 解析body
	 */
	public static HttpBody getHttpBody(FullHttpRequest request, BodyType bodyType) {
		return new HttpBody(request.content(), bodyType);
	}
	
	/**
	 * 设置http参数
	 * 
	 * @param ctx
	 * @param request
	 * @return
	 */
	public static HttpParam getHttpParam(ChannelHandlerContext ctx, FullHttpRequest request) {
		return new HttpParam(getParamMap(request));
	}

	/**
	 * Get获取uri参数
	 */
	private static Map<String, String> getParamMap(FullHttpRequest request) {
		Map<String, String> params = new HashMap<String, String>();

		QueryStringDecoder decoder = new QueryStringDecoder(request.uri());

		Map<String, List<String>> parame = decoder.parameters();
		for (Entry<String, List<String>> entry : parame.entrySet()) {
			params.put(entry.getKey(), entry.getValue().get(0));
		}

		return params;
	}

	/**
	 * 获取客户端IpAddress
	 */
	public static String getIp(ChannelHandlerContext ctx) {
		return ctx.channel().remoteAddress().toString().replaceAll(Constants.ROOT_DIR, Constants.EMPTY_STRING)
				.split(Constants.COLON)[0];
	}

	/**
	 * 获取请求URI
	 */
	public static String getURI(FullHttpRequest request) {
		String uri = request.uri();

		if (uri.indexOf(Constants.PARAM_SPLIT) != -1) {
			uri = uri.substring(0, request.uri().indexOf(Constants.PARAM_SPLIT));
		}
		
		String endPoint = config.getEndPoint();

		if(!StringUtils.isEmpty(endPoint)) {
			if(uri.startsWith(endPoint)) {
				uri = uri.replaceFirst(endPoint, Constants.EMPTY_STRING);
				
				if(StringUtils.isEmpty(uri)) {
					uri = Constants.ROOT_DIR;
				}
				
			} else {
				uri = Constants.EMPTY_STRING;
			}
		}

		return uri;
	}

}
